﻿using System.Text;
using VideoTools.SubtitleEdit.SubtitleFormats;

namespace VideoTools.SubtitleEdit.Common
{
    public class SubtitleEncode
    {
        public const int MaxFileSize = 1024 * 1024 * 20; // 20 MB

        public List<Paragraph> Paragraphs { get; private set; }

        public string Header { get; set; } = string.Empty;
        public string Footer { get; set; } = string.Empty;

        public string FileName { get; set; }

        public static int MaximumHistoryItems => 100;

        public SubtitleFormat OriginalFormat { get; set; }
        public Encoding OriginalEncoding { get; private set; }

        //public List<HistoryItem> HistoryItems { get; }

        public SubtitleEncode() : this(new List<Paragraph>())
        {
        }


        public SubtitleEncode(List<Paragraph> paragraphs)
        {
            Paragraphs = paragraphs;
            FileName = "Untitled";
        }

        /// <summary>
        /// Copy constructor (without history).
        /// </summary>
        /// <param name="subtitle">Subtitle to copy</param>
        /// <param name="generateNewId">Generate new ID (guid) for paragraphs</param>
        public SubtitleEncode(SubtitleEncode subtitle, bool generateNewId = true)
        {
            if (subtitle == null)
            {
                FileName = "Untitled";
                Paragraphs = new List<Paragraph>();
                return;
            }

            Paragraphs = new List<Paragraph>(subtitle.Paragraphs.Count);
            foreach (var p in subtitle.Paragraphs)
            {
                Paragraphs.Add(new Paragraph(p, generateNewId));
            }

            Header = subtitle.Header;
            Footer = subtitle.Footer;
            FileName = subtitle.FileName;
            OriginalFormat = subtitle.OriginalFormat;
            OriginalEncoding = subtitle.OriginalEncoding;
        }


        /// <summary>
        /// Get the paragraph of index, null if out of bounds
        /// </summary>
        /// <param name="index">Index of wanted paragraph</param>
        /// <returns>Paragraph, null if index is index is out of bounds</returns>
        public Paragraph GetParagraphOrDefault(int index)
        {
            if (Paragraphs == null || Paragraphs.Count <= index || index < 0)
            {
                return null;
            }

            return Paragraphs[index];
        }

        /// <summary>
        /// Concatenates all Paragraphs Text property, using the default NewLine string between each Text.
        /// </summary>
        /// <returns>Concatenated Text property of all Paragraphs.</returns>
        public string GetAllTexts(int stopAfterBytes)
        {
            var max = Paragraphs.Count;
            const int averageLength = 40;
            var sb = new StringBuilder(max * averageLength);
            for (var index = 0; index < max; index++)
            {
                sb.AppendLine(Paragraphs[index].Text);
                if (sb.Length > stopAfterBytes)
                {
                    return sb.ToString();
                }
            }

            return sb.ToString();
        }


        /// <summary>
        /// Concatenates all Paragraphs Text property, using the default NewLine string between each Text.
        /// </summary>
        /// <returns>Concatenated Text property of all Paragraphs.</returns>
        public string GetAllTexts()
        {
            var max = Paragraphs.Count;
            const int averageLength = 40;
            var sb = new StringBuilder(max * averageLength);
            for (var index = 0; index < max; index++)
            {
                sb.AppendLine(Paragraphs[index].Text);
            }

            return sb.ToString();
        }

        public void Renumber()
        {
            int startNumber = 0;
            var number = startNumber;
            int l = Paragraphs.Count + number;
            while (number < l)
            {
                var p = Paragraphs[number - startNumber];
                p.Number = number++;
            }
        }

        public int RemoveEmptyLines()
        {
            var count = Paragraphs.Count;
            if (count <= 0)
            {
                return 0;
            }

            var firstNumber = Paragraphs[0].Number;
            for (var i = Paragraphs.Count - 1; i >= 0; i--)
            {
                var p = Paragraphs[i];
                if (p.Text.IsOnlyControlCharactersOrWhiteSpace())
                {
                    Paragraphs.RemoveAt(i);
                }
            }

            if (count != Paragraphs.Count)
            {
                Renumber();
            }

            return count - Paragraphs.Count;
        }
    }
}
